#!/usr/bin/env bash
# keep-elasticsearch-during -- Keeps an elasticsearch instance running while the given command is running
# $ keep-elasticsearch-during [ES_OPTS]... -- COMMAND [ARG]...
# Sets environment ELASTICSEARCH_RUNNING=true when running COMMAND.
#
##
# Author: Jaeho Shin <netj@cs.stanford.edu>
# Created: 2015-07-31
set -eu

# default settings
: ${ELASTICSEARCH_BASEURL:=http://localhost:9200} # TODO randomize port?
: ${ELASTICSEARCH_HOME:="$PWD"/search}

# parse all command-line args down to a -- as elasticsearch options
[[ $# -gt 0 ]] ||
    usage "$0" "Missing -- and COMMAND"
esOpts=()
while [[ $# -gt 0 ]]; do
    o=$1; shift
    [[ "$o" != -- ]] || break
    esOpts+=("$o")
done
[[ $# -gt 0 ]] ||
    usage "$0" "Missing COMMAND"

# make sure elasticsearch instance is available
elasticsearch-is-up() {
    curl -fs -XGET "$ELASTICSEARCH_BASEURL/_status" >/dev/null
}
case $ELASTICSEARCH_BASEURL in
    http://localhost:*)
        port=${ELASTICSEARCH_BASEURL#http://localhost:}
        port=${port%%/*}
        # make sure search repo is initialized
        mkdir -p "$ELASTICSEARCH_HOME"/{config,data,logs}
        [[ -e "$ELASTICSEARCH_HOME"/config/elasticsearch.yml ]] || cp -f "$MINDBENDER_HOME"/depends/bundled/elasticsearch/prefix/*/config/elasticsearch.yml "$ELASTICSEARCH_HOME"/config/
        [[ -e "$ELASTICSEARCH_HOME"/config/logging.yml       ]] || cp -f "$MINDBENDER_HOME"/depends/bundled/elasticsearch/prefix/*/config/logging.yml       "$ELASTICSEARCH_HOME"/config/
        terminate-local-elasticsearch() {
            local pidfile="$ELASTICSEARCH_HOME"/elasticsearch.pid
            local pid=$(cat "$pidfile" 2>/dev/null)
            # kill the elasticsearch process
            [[ -z "$pid" ]] || kill -TERM $pid ||
                # or just clean up the stale PID file if can't kill
                rm -f "$ELASTICSEARCH_HOME"/elasticsearch.pid
        }
        # terminate if something's running locally but perhaps on a different port
        if [[ -e "$ELASTICSEARCH_HOME"/elasticsearch.pid ]]; then
            elasticsearch-is-up || terminate-local-elasticsearch
        fi
        # if no instance is running here yet
        if ! [[ -e "$ELASTICSEARCH_HOME"/elasticsearch.pid ]]; then
            if elasticsearch-is-up; then
                # port may be occupied
                error "$port: port is already used, try another one, e.g.: export ELASTICSEARCH_BASEURL=http://localhost:92${RANDOM:0:2}"
            else
                # launch an isolated elasticsearch
                msg "Launching Elasticsearch for $ELASTICSEARCH_BASEURL from $ELASTICSEARCH_HOME"
                esOpts+=(
                    # in background with a PID file
                    -d -p "$ELASTICSEARCH_HOME"/elasticsearch.pid

                    # some paths outside path.home
                    -D es.path.config="$ELASTICSEARCH_HOME"/config
                    -D es.path.data="$ELASTICSEARCH_HOME"/data
                    -D es.path.logs="$ELASTICSEARCH_HOME"/logs

                    # override ports
                    -D es.http.port=$port

                    # to completely isolate instance, disable discovery, use local mode
                    # (See: http://stackoverflow.com/a/16432759/390044)
                    -D es.node.local=true

                    # alternatively, to isolate local instances, use different cluster name (slower)
                    #-D es.cluster.name=mindbender-$HOSTNAME-$port
                    #-D es.transport.tcp.port=$(($port + 100))
                    #-D discovery.zen.ping.multicast.enabled=false 
                )
                elasticsearch "${esOpts[@]:-}"
                # and terminate the instance upon exit
                trap terminate-local-elasticsearch EXIT
            fi
        fi
        # wait until the instance boots up
        until elasticsearch-is-up; do sleep 0.$RANDOM; done
        ;;

    *)
        # skip setup since ELASTICSEARCH_BASEURL is not localhost
        # make sure the elasticsearch instance is there
        elasticsearch-is-up ||
            error "$ELASTICSEARCH_BASEURL: Elasticsearch not responding"
esac

# run given command
export ELASTICSEARCH_BASEURL ELASTICSEARCH_HOME ELASTICSEARCH_RUNNING=true
"$@"
